package ubc;




import java.io.Serializable;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/* a synchronized queue */
public class Queue implements Serializable{

    /* the actual queue */
    private LinkedList<Object>  _queue ;

    /* the constructor - it simply creates the LinkedList where the queue elements are stored */
    public Queue() {
        _queue = new LinkedList<Object>();
    }

    public synchronized void set(Queue q) {
        for(int i=0; i<q.size(); i++) {
            enqueue(q._queue.remove());
        }
        q = null;
    }
    
    /* gets the first element of the queue or blocks if the queue is empty */
    public synchronized Object dequeue() throws InterruptedException {
        while (_queue.isEmpty()) {
            wait();
        }
        return _queue.removeFirst();
    }

    public synchronized Queue dequeue(int num) throws InterruptedException {
        Queue q = new Queue();
        for(int i=0; i<num; i++) {
            if(!_queue.isEmpty()) {
                q.enqueue(dequeue());
            }
        }
        return q;
    }

    /* add a new element to the queue */
    public synchronized void enqueue(Object obj) {

    	// If the queue does not already contain a copy of obj,
    	// and the queue has less than maxQueueSize element,
    	// then add it to our queue
    	if( (_queue.contains(obj) == false) ) {
	        _queue.addLast(obj);
	        notify();
    	}
    }

    /* add a new element to the queue */
    public synchronized void enqueueFirst(Object obj) {

    	// If the queue does not already contain a copy of obj,
    	// and the queue has less than maxQueueSize element,
    	// then add it to our queue
    	if( (_queue.contains(obj) == false) ) {
	        _queue.addFirst(obj);
	        notify();
    	}
    }
    
    public synchronized Boolean contains(Object obj) {
    	if(_queue.contains(obj)) {
    		return true;
    	} else {
    		return false;
    	}
    }

    public synchronized int size() {
    	return _queue.size();
    }

    public synchronized String toString() {
        List<String> l = new ArrayList<String>();
        for (int i=0; i<size(); i++) {
            l.add( (String)_queue.get(i) );
        }
        return l.toString();
    }

}
